package com.chery.media.utils

import com.aleyn.cache.CacheManager
import com.aleyn.cache.NetCacheInterceptor
import com.blankj.utilcode.util.GsonUtils
import com.blankj.utilcode.util.Utils
import com.chery.media.app.base.BaseResult
import com.chery.media.common.Constant.BASE_URL
import com.chery.media.contacts.EventContacts
import com.chery.media.contacts.StorageContacts
import com.chery.media.library.adapter.FlowAdapterFactory
import com.chery.media.library.extend.getStorageString
import com.chery.media.library.network.SSLContextUtil
import com.franmontiel.persistentcookiejar.PersistentCookieJar
import com.franmontiel.persistentcookiejar.cache.SetCookieCache
import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor
import com.jeremyliao.liveeventbus.LiveEventBus
import okhttp3.ConnectionPool
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Response
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.security.cert.CertificateException
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit
import javax.net.ssl.X509TrustManager

/**
 *   @auther : Aleyn
 *   time   : 2019/09/04
 */
class RetrofitClient {

    companion object {
        fun getInstance() = SingletonHolder.INSTANCE
        private lateinit var retrofit: Retrofit
    }

    private object SingletonHolder {
        val INSTANCE = RetrofitClient()
    }

    private val cookieJar: PersistentCookieJar by lazy {
        PersistentCookieJar(SetCookieCache(), SharedPrefsCookiePersistor(Utils.getApp()))
    }

    init {
        retrofit = Retrofit.Builder()
            .client(getOkHttpClient())
            .addCallAdapterFactory(FlowAdapterFactory.create(true))
            .addConverterFactory(GsonConverterFactory.create())
            .baseUrl(BASE_URL)
            .build()
    }

    private fun getOkHttpClient(): OkHttpClient {
        val sslContext = SSLContextUtil.defaultSLLContext
        val socketFactory = sslContext?.socketFactory
        return OkHttpClient.Builder().apply {
            //添加Cookies自动持久化
            cookieJar(cookieJar)
            connectTimeout(20L, TimeUnit.SECONDS)
            writeTimeout(20L, TimeUnit.SECONDS)
            connectionPool(ConnectionPool(8, 15, TimeUnit.SECONDS))
            addInterceptor(NetCacheInterceptor(CacheManager(Utils.getApp().cacheDir)))
            addInterceptor(HttpLoggingInterceptor().apply {
                level = HttpLoggingInterceptor.Level.BODY
            })
//            addInterceptor(HeadInterceptor())
//            addInterceptor(TokenInterceptor())
            if (socketFactory != null)
                sslSocketFactory(socketFactory, object : X509TrustManager {
                    @Throws(CertificateException::class)
                    override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {
                    }

                    @Throws(CertificateException::class)
                    override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {
                    }

                    override fun getAcceptedIssuers(): Array<X509Certificate?> {
                        return arrayOfNulls(0)
                    }
                })
            hostnameVerifier(SSLContextUtil.HOSTNAME_VERIFIER)
        }.build()
    }

    fun <T> create(service: Class<T>?): T =
        retrofit.create(service!!) ?: throw RuntimeException("Api service is null!")
}

class HeadInterceptor : Interceptor {

    override fun intercept(chain: Interceptor.Chain): Response {
        val builder = chain.request().newBuilder()
        val token = getStorageString(StorageContacts.USER_TOKEN) ?: ""
        with(builder) {
            addHeader("token", token)
            addHeader("source", "Android")
        }
        return chain.proceed(builder.build())
    }

}

class TokenInterceptor : Interceptor {

    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request()
        val response = chain.proceed(request)
        val responseBody = response.body
        return try {
            chain.proceed(request)
        } catch (e: Exception) {
            e.printStackTrace()
            chain.proceed(request)
        }
    }

}